<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>事件处理</title>
    <style>
        a {
            color: blue;
            text-decoration: underline;
        }

        .for-scroll {
            height: 80px;
            width: 200px;
            border: 1px solid #cccccc;
            overflow: scroll;
        }
    </style>
    <script src="../vue.js"></script>
</head>
<body>
<!--v-on指令：监听dom事件-->
<fieldset>
    <legend>监听事件</legend>
    <div id="app">
        <!--v-on中直接计算counter的值-->
        <button v-on:click="count += 1">Add 1</button>
        <p>The button above has been clicked {{ count }} times.</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                count: 0
            }
        });
    </script>
</fieldset>

<fieldset>
    <legend>事件处理方法</legend>
    <div id="app2">
        <!-- `greet` 是在下面定义的方法名 -->
        <button v-on:click="greet">Greet</button>
        <button v-on:click="greetByObject">Greet by vue instance</button>
    </div>
    <script>
        var app2 = new Vue({
            el: '#app2',
            data: {
                name: 'vuejs'
            }, methods: {
                /*event是js原生事件对象*/
                greet: function (event) {
                    alert('Hello ' + this.name + "! 点击了：" + event.target.tagName);
                },
                greetByObject: function (event) {
                    // 也可以用 JavaScript 直接调用方法
                    app2.greet(event)
                }
            }
        });
    </script>
</fieldset>

<fieldset>
    <legend>内联处理器中的方法</legend>
    <div id="app3">
        <!--内联访问事件方法-->
        <button v-on:click="say('hi')">Say hi</button>
        <button v-on:click="say('what')">Say what</button>
        <!--内联访问原生event对象，使用特殊变量$event传入-->
        <button v-on:click="warn('Form cannot be submitted yet.', $event)">warn</button>
    </div>
    <script>
        var app3 = new Vue({
            el: '#app3',
            data: {}, methods: {
                say: function (msg) {
                    alert(msg)
                },
                warn: function (msg, event) {
                    /*访问原生event对象*/
                    if (event) {
                        event.preventDefault()
                    }
                    alert(msg);
                }
            }
        })
    </script>
</fieldset>

<fieldset>
    <legend>事件修饰符</legend>
    <!--在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点，
    但更好的方式是：方法只有纯粹的数据逻辑，而不是去处理 DOM 事件细节。
    Vue.js为v-on提供了事件修饰符，来处理事件的一些行为：
    .stop：阻止事件继续传播
    .prevent：阻止默认行为
    .capture：使用事件捕获模式，即内部元素触发的事件先在此处理，然后才交由内部元素进行处理
    .self：只当在 event.target 是当前元素自身时触发处理函数，即事件不是从内部元素触发的
    .once：事件将只会触发一次
    .passive：滚动事件的默认行为 (即滚动行为) 将会立即触发，而不会等待 `onScroll` 完成，这其中包含 `event.preventDefault()` 的情况
    -->
    <div id="app4">
        <div>
            <label>click: </label>
            <a v-on:click="link">go to https://belonk.com</a>
        </div>
        <div>
            <!-- 阻止单击事件继续传播 -->
            <label>click.stop: </label>
            <a v-on:click.stop="link">go to https://belonk.com</a>
        </div>
        <div>
            <label>click.stop.prevent: </label>
            <!-- 修饰符可以串联 -->
            <a v-on:click.stop.prevent="link">go to
                https://belonk.com</a>
        </div>
        <div>
            <form v-on:submit="onSubmit" action="https://belonk.com">
                <button type="submit">submit form</button>
            </form>

            <!-- 提交事件不再重载页面 -->
            <form v-on:submit.prevent="onSubmit" action="https://belonk.com">
                <button type="submit">submit form1</button>
            </form>

            <!-- 只有修饰符 -->
            <form v-on:submit.prevent action="https://belonk.com">
                <button type="submit">submit form2</button>
            </form>
        </div>

        <!--
        添加事件监听器时使用事件捕获模式
        即内部元素触发的事件先在此处理，然后才交由内部元素进行处理
        示例先输出outter div，再输出inner a
        -->
        <div>
            <label>click.capture事件捕捉: </label>
            <div v-on:click.capture="alert('outter div')">
                <a v-on:click="alert('inner a')">inner a</a>
            </div>
        </div>

        <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
        <!-- 即事件不是从内部元素触发的 -->
        <div>
            <label>click.self: </label>
            <!--内部元素不会出发外部元素事件，点击外部元素div才会出发外部元素事件-->
            <div v-on:click.self="alert('outter div')"
                 style="border: 1px solid red; display: inline-block;padding: 10px;">
                <a v-on:click="alert('inner a')">inner a</a>
            </div>
        </div>

        <div>
            <label>click.once: </label>
            <a v-on:click.once="alert('只会触发一次!')">only once</a>
        </div>

        <div>
            <label>scroll.passive: </label>
            <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
            <!-- 而不会等待 `onScroll` 完成  -->
            <!-- 这其中包含 `event.preventDefault()` 的情况 -->
            <div v-on:scroll.passive="onScroll" class="for-scroll">
                <p>{{content}}</p>
            </div>
        </div>
    </div>

    <script>
        var app4 = new Vue({
            el: '#app4',
            data: {content: ''},
            created: function () {
                let it = setInterval(() => {
                    this.content += Math.random() + '\n';
                }, 200);
                setTimeout(() => {
                    clearInterval(it);
                }, 3000);
            },
            methods: {
                link: function () {
                    window.open("https://belonk.com", "_blank");
                },
                onSubmit: function (event) {
                    alert(1);
                },
                alert: function (msg) {
                    alert(msg);
                },
                onScroll: function () {
                    setTimeout(() => {
                        console.log('onScroll执行完成！');
                    }, 1000)
                }
            }
        })
    </script>
</fieldset>

<fieldset>
    <legend>按键修饰符</legend>
    <!--
        Vue 允许为 v-on 在监听键盘事件时添加按键修饰符
    -->
    <div id="app5">
        <label>获取keycode：</label>
        <input v-on:keyup="getKeycode" :value="keycode" placeholder="press a key">

        <!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
        <input v-on:keyup.enter="alert('pressed enter!')" placeholder="press enter">

        <!--处理函数只会在 $event.key 等于 PageDown 时被调用-->
        <input v-on:keyup.page-down="alert('Pressed PageDown!')" placeholder="press pagedown">

        <!--按键码 keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持，但Vue也允许使用 keyCode attribute-->
        <input v-on:keyup.13="alert('pressed enter by keycode!')" placeholder="press enter by keycode">

        <!--
        为了在必要的情况下支持旧浏览器，Vue 提供了绝大多数常用的按键码的别名：
        .enter
        .tab
        .delete (捕获“删除”和“退格”键)
        .esc
        .space
        .up
        .down
        .left
        .right
        -->
        <input v-on:keyup.esc="alert('pressed esc by alias!')" placeholder="press esc by alias">

        <!--你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名-->
        <input type="text" v-on:keyup.my-enter="alert('pressed enter by custom alias')"
               placeholder="press enter by custom alias">
    </div>

    <script>
        Vue.config.keyCodes = {
            // camelCase 不可用
            myEnter: 13,
            // 取而代之的是 kebab-case 且用双引号括起来
            "my-enter": 13,
        }
        var app5 = new Vue({
            el: '#app5',
            data: {
                keycode: ''
            },
            methods: {
                alert: function (msg) {
                    alert(msg);
                },
                getKeycode: function (e) {
                    this.keycode = e.key + " - " + e.keyCode + " - " + e.code;
                }
            }
        });
    </script>
</fieldset>

<fieldset>
    <legend>系统修饰符</legend>
    <!--
        可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
        .ctrl
        .alt
        .shift
        .meta
    -->
    <div id="app6">
        <div>
            <!-- alt + c -->
            <input v-on:keyup.alt.67="alert('you pressed alt + c')" placeholder="ALT + C"/>
            <!-- ctrl + click在mac上冲突，改为alt -->
            <button v-on:click.alt="alert('you pressed alt + click!')">alt + click</button>
        </div>

        <div>
            <label>.exact</label>
            <!--.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。-->
            <!-- 即使 ctrl 或 Shift 被一同按下时也会触发 -->
            <button v-on:click.alt="alert('只要按了alt就能触发，不管是否同时按下其他键')">按下alt和shift/ctrl再点击试试</button>

            <!-- 有且只有 alt 被按下的时候才触发 -->
            <button v-on:click.alt.exact="alert('仅有按了alt才能触发')">仅按下alt再点击试试</button>

            <!-- 没有任何系统修饰符被按下的时候才触发 -->
            <button v-on:click.exact="alert('没有按下任何修饰键才会被触发')">不要按ctrl/alt/meta/shift点击</button>
        </div>
    </div>

    <script>
        var app6 = new Vue({
            el: '#app6',
            data: {},
            methods: {
                alert: function (msg) {
                    alert(msg);
                }
            }
        });
    </script>
</fieldset>

<fieldset>
    <legend>鼠标按钮修饰符</legend>
    <div id="app7">
        <!--
            .left
            .right
            .middle
            这些修饰符会限制处理函数仅响应特定的鼠标按钮。
        -->
        <input v-on:click.left="alert('clicked left key of your mouse')" placeholder="click left key">
        <input v-on:click.middle="alert('clicked middle key of your mouse')" placeholder="click middle key">
        <!--阻止默认事件-->
        <input v-on:click.right.prevent="alert('clicked right key of your mouse')" placeholder="click right key">
    </div>
    <script>
        var app7 = new Vue({
            el: '#app7',
            data: {},
            methods: {
                alert: function (msg) {
                    alert(msg);
                }
            }
        });
    </script>
</fieldset>
</body>
</html>
